package dating;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class TcpThread extends Thread{
    
    //定义变量
    public static InetAddress hostAddress;//主机IP地址
    public static int MIN_port;            //The minimal number of port
    public static int MAX_port;            //The maximal number of port
    private int NUM_thread;                //线程总数
    public static int type;                //查询方式，0为IP方式1为主机名查询方式
    
    public static int ip1;//IP前三位
    public static int ip2;//IP4~6位
    public static int ip3;//IP7~9位
    public static int ipstart;//起始IP地址最后四位
    public static int ipend;//结束IP地址最后四位
    public static String ipAll;//完整的IP地址
    
    String nameHost = "";//扫描的主机名称或IP地址
    String typeport = "0";//端口类别
    
    static Integer  maxThread = 5;
    
    /**
     * 构造函数
     */
    public TcpThread( String name, int numthread ){
        super(name);
        this.NUM_thread = numthread;
    }
    
    /**
     * run()运行函数
     */
    public void run( ) {
        
        int h = 0;//IP address
        int i = 0;//port number
        
        Socket theTcpSocket;
        
        //根据IP地址进行扫描
        if( 0 == type ){
            //IP地址循环扫描
            for( h = ipstart; h <= ipend; h++){
                ipAll = "" + ip1 + "." + ip2 + "." + ip3 + "." + h;
                nameHost = ipAll;
                
                try{
                    hostAddress = InetAddress.getByName( ipAll );
                }catch( UnknownHostException e){}
                
                //不同端口循环扫描
                for( i = MIN_port; i < MAX_port + maxThread;
                        i += maxThread ){
                    try{
                        theTcpSocket = new Socket(hostAddress, i);
                        theTcpSocket.close();
                        
                        System.out.println( nameHost +":"+i);
                        
                        switch( i ){//其实这儿可以不用switch，直接用个hash表记录就可以
                            case 21:
                                typeport = "(FTP)";
                                break;
                            case 23:
                                typeport = "(TELNET)";
                                break;
                            case 25:
                                typeport = "SMTP";
                                break;
                            case 80:
                                typeport = "HTTP";
                                break;
                            case 110:
                                typeport = "POP";
                                break;
                            case 139:
                                typeport = "netBIOS";
                                break;
                            case 1433:
                                typeport = "SQL Server";
                                break;
                            case 3389:
                                typeport = "Terminal Service";
                                break;
                            case 443:
                                typeport = "HTTPS";
                                break;
                            case 1521:
                                typeport = "Oracle";
                                break;
                        }
                        
                        //端口没有特定类型
                        if( typeport.equals("0")){
                        	System.out.println("\n");
                        }else{
                        	System.out.println(":" + typeport + "\n");
                        }            
                    }catch( IOException e){}
                }
            }
            if( i == MAX_port + maxThread){
                System.out.println("\n" + "扫描完成...");
            }
        }
        
        //按主机名进行端口扫描
        if( 1 == type ){
            for( i = MIN_port + NUM_thread; i < MAX_port + maxThread;
                    i += maxThread ) {
                try{
                    theTcpSocket = new Socket( hostAddress, i );
                    theTcpSocket.close();
                    System.out.println(" " + i);
                    switch( i ){//其实这儿可以不用switch，直接用个hash表记录就可以
                        case 21:
                            typeport = "(FTP)";
                            break;
                        case 23:
                            typeport = "(TELNET)";
                            break;
                        case 25:
                            typeport = "SMTP";
                            break;
                        case 80:
                            typeport = "HTTP";
                            break;
                        case 110:
                            typeport = "POP";
                            break;
                        case 139:
                            typeport = "netBIOS";
                            break;
                        case 1433:
                            typeport = "SQL Server";
                            break;
                        case 3389:
                            typeport = "Terminal Service";
                            break;
                        case 443:
                            typeport = "HTTPS";
                            break;
                        case 1521:
                            typeport = "Oracle";
                            break;
                    }
                    if( typeport.equals("0") ){
                        System.out.println("\n");
                    }else{
                    	System.out.println(":" + typeport + "\n");
                    }
                }catch( IOException e){
                    
                }
            }
            if( i == MAX_port + maxThread){
            	System.out.println("\n" + "扫描完成...");
                
            }        
        }//End of if
    }
    
    public static void main(String[] args) {
		
    	int minPort;
        int maxPort;
        int maxThread = TcpThread.maxThread;
        TcpThread.type = 0;
        int ip1 = 192;
        int ip2 = 168;
        int ip3 = 0;
        int ipstart = 0;
        int ipend = 0;
        
    	String ipaddress ;
    	boolean isSelected = false;
    	String nameHost = "";
    	
    	
        
        //判断是否是合理的IP地址
        if(ip1 < 0 || ip1 > 255 || ip2 < 0 || ip2 > 255 ||
           ip3 < 0 || ip3 > 255 || ipstart < 0 || ipstart > 255 ){
            System.out.println("IP地址为0~255的整数");
            return ;
        }else{
            TcpThread.ip1 = ip1;
            TcpThread.ip2 = ip2;
            TcpThread.ip3 = ip3;
            TcpThread.ipstart = ipstart;
        }
        //判断目标IP地是否合理
        if( ipend < 0 || ipend > 255 ){
            System.out.println("目标IP地址的范围是0~255");
            return;
        }else{
            TcpThread.ipend = ipend;
        }
        
        ipaddress = "" + ip1 + ip2 + ip3 + ipstart;
        
        /**
         * 判断IP地址的有效性
         */
        try{
            TcpThread.hostAddress = InetAddress.getByName(ipaddress);
        }catch( UnknownHostException e){
            System.out.println("错误的IP或IP地址不可到达！");
            return;
        }
        
        if( isSelected){
            TcpThread.type = 1;
            /**
             * 判断主机名的有效性
             */
            try{
                TcpThread.hostAddress = InetAddress.getByName(nameHost);
            }catch( UnknownHostException e){ 
            	System.out.println("错误的域名或地址不可到达！");
                return;
            }
        }
        /**
         * 判断端口号的有效性
         */
        try{
            minPort = 0;
            maxPort = 65535;
        }catch( NumberFormatException e ){
            System.out.println("错误的端口号或端口号和线程数必须为整数");
            return;
        }
        /**
         * 判断最小端口号的有效范围
         * 判断条件大于0小于65535最大端口号大于最小端口号
         */
        if( minPort < 0 || minPort > 65535 || minPort > maxPort ){
            System.out.println("端口号范围：0~65535,并且最大端口号应大于最小端口号！");
            return;
        }else{
            TcpThread.MIN_port = minPort;
        }
        /**
         * 判断最大端口号的有效范围
         */
        if( maxPort < 0 || maxPort > 65535 || maxPort < minPort ){
            System.out.println("端口号范围：0~65535,并且最大端口号应大于最小端口号！");
            return;
        }else{
            TcpThread.MAX_port = maxPort;
        }
        /**
         * 判断线程数的有效范围
         * 判断条件 大于1且小于200
         */
        if( maxThread < 1 || maxThread > 200 ){
        	 System.out.println("线程数的有效范围是1~200");
            return;
        }
        System.out.println("线程数" + TcpThread.maxThread + "\n");
        
    	
    	 /**
         * 启动线程
         */
        for( int i = 0; i < TcpThread.maxThread; i++ ){
            new TcpThread("T" + i, i).start();
        }
	}
}